package com.whcoding.test.common;

import com.google.common.collect.Lists;
import com.whcoding.test.constant.BaseConstant;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @program: spring-boot-learning
 * @description:
 * @author: whcoding
 * @create: 2022-04-01 15:52
 **/
public class DefaultValueUtils<T> {
	private static final Logger log = LoggerFactory.getLogger(DefaultValueUtils.class);

	/**
	 * 将传入对象的空属性赋上默认值
	 * 目前支持 String、Date、Long、Double，Integer BigDecimal
	 **/
	public static <T> T toDefaultInstance(Object target) {
		Map<String, Field> targetMap = new HashMap<>(16);

		Class tempClass = target.getClass();
		while (tempClass != null) {
			targetMap.putAll(CacheFieldMap.getFieldMap(tempClass));
			tempClass = tempClass.getSuperclass();
		}

		targetMap.values().forEach((it) -> {
			Field field = targetMap.get(it.getName());
			Class<?> fieldType = field.getType();

			if (field != null) {
				it.setAccessible(true);
				field.setAccessible(true);
				try {
					if (Objects.isNull(it.get(target))) {

						if (fieldType.equals(Integer.class)) {
							it.set(target, 0);
							return;
						}
						if (fieldType.equals(String.class)) {
							it.set(target, StringUtils.EMPTY);
							return;
						}
						if (fieldType.equals(Long.class)) {
							it.set(target, 0L);
							return;
						}
						if (fieldType.equals(BigDecimal.class)) {
							it.set(target, BigDecimal.ZERO);
							return;
						}
						if (fieldType.equals(Double.class)) {
							it.set(target, BigDecimal.ZERO.doubleValue());
							return;
						}
						if (fieldType.equals(Date.class)) {
							it.set(target, BaseConstant.DEFAULT_DATE);
							return;
						}
					}
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		});
		return (T) target;
	}

	private static class CacheFieldMap {
		private static Map<String, Map<String, Field>> cacheMap = new HashMap<>();

		private static Map<String, Field> getFieldMap(Class clazz) {
			Map<String, Field> result = cacheMap.get(clazz.getName());
			if (result == null) {
				synchronized (CacheFieldMap.class) {
					if (result == null) {
						Map<String, Field> fieldMap = new HashMap<>(16);
						for (Field field : clazz.getDeclaredFields()) {
							fieldMap.put(field.getName(), field);
						}
						cacheMap.put(clazz.getName(), fieldMap);
						result = cacheMap.get(clazz.getName());
					}
				}
			}
			return result;
		}
	}

	/**
	 * 设置默认值
	 *
	 * @param entily
	 * @return
	 */
	public T setDefaultValue(T entily) {

		Field[] fields = entily.getClass().getDeclaredFields();
		// 循环获取字段名称数据
		for (int i = 0; i < fields.length; i++) {
			// 获取当前的属性名称
			String name = fields[i].getName();
			// 判断当前是否为序列号名称 （序列号名称必须为：serialVersionUID ，否则会报NoSuchMethodException异常）
			if ("serialVersionUID".equals(name)) {
				//跳出当前循环，进入下一次循环
				continue;
			}
			//将属性的首先字符大写，方便构造GET，SET方法
			name = name.substring(0, 1).toUpperCase() + name.substring(1);
			try {
				// 获取属性类型
				String typeName = fields[i].getGenericType().toString();
				// 获取属性GET方法
				Method get = entily.getClass().getMethod("get" + name);
				// 通过属性的GET方法获取属性对应值
				Object value = get.invoke(entily);
				// 判断属性类型为BigDecimal类型
				if ("class java.math.BigDecimal".equals(typeName)) {
					// 属性对应值是否为空
					if (value != null) {
					} else {
						// 获取属性SET方法（注意：方法的参数值类型必须设置正确，则报方法不存在异常）
						Method set = entily.getClass().getMethod("set" + name, BigDecimal.class);
						// 通过SET方法给予赋值
						set.invoke(entily, BaseConstant.DEFAULT_BIGDECIMAL_VALUE);
					}
				}
				// 判断属性类型为Long类型
				if ("class java.lang.Long".equals(typeName)) {
					if (value != null) {
					} else {
						Method set = entily.getClass().getMethod("set" + name, Long.class);
						set.invoke(entily, BaseConstant.DEFAULT_LONG_VALUE);
					}
				}
				// 判断属性类型为Long类型
				if ("class java.lang.Integer".equals(typeName)) {
					if (value != null) {
					} else {
						Method set = entily.getClass().getMethod("set" + name, Integer.class);
						if ("valid".equals(name)) {
							set.invoke(entily, BaseConstant.DEFAULT_VALID_ONE);
						} else {
							set.invoke(entily, BaseConstant.DEFAULT_NEGETIVE_ONE);
						}
					}
				}
				// 判断属性类型为Double类型
				if ("class java.lang.Double".equals(typeName)) {
					if (value != null) {
					} else {
						Method set = entily.getClass().getMethod("set" + name, Double.class);
						set.invoke(entily, BaseConstant.DEFAULT_DOUBLE_VALUE);
					}
				}
				// 判断属性类型为Float类型
				if ("class java.lang.Float".equals(typeName)) {
					if (value != null) {
					} else {
						Method set = entily.getClass().getMethod("set" + name, Float.class);
						set.invoke(entily, BaseConstant.DEFAULT_FLOAT_VALUE);
					}
				}
				// 判断属性类型为String类型
				if ("class java.lang.String".equals(typeName)) {
					if (value != null) {
					} else {
						Method set = entily.getClass().getMethod("set" + name, String.class);
						set.invoke(entily, BaseConstant.DEFAULT_STRING_VALUE);
					}
				}
				// 判断属性类型为Date类型
				if ("class java.utils.Date".equals(typeName)) {
					if (value != null) {
					} else {
						Method set = entily.getClass().getMethod("set" + name, Date.class);
						set.invoke(entily, BaseConstant.DEFAULT_DATE);
					}
				}
				// 判断属性类型为Date类型
				if ("class java.time.Instant".equals(typeName)) {
					if (value != null) {
					} else {
						Method set = entily.getClass().getMethod("set" + name, Instant.class);
						set.invoke(entily, BaseConstant.DEFAULT_INSTANT_VALUE);
					}
				}
				// 判断属性类型为LocalDate类型
				if ("class java.time.LocalDate".equals(typeName)) {
					if (value != null) {
					} else {
						Method set = entily.getClass().getMethod("set" + name, LocalDate.class);
						set.invoke(entily, BaseConstant.DEFAULT_LOCALDATE_VALUE);
					}
				}
				// 判断属性类型为LocalDateTime类型
				if ("class java.time.LocalDateTime".equals(typeName)) {
					if (value != null) {
					} else {
						Method set = entily.getClass().getMethod("set" + name, LocalDateTime.class);
						set.invoke(entily, BaseConstant.DEFAULT_LOCALDATETIME_VALUE);
					}
				}

			} catch (Exception e) {
				log.error(e.getMessage(), e);
			}
		}
		log.info("结束的参数,{}", entily);
		return entily;
	}

	/**
	 * 设置默认值
	 *
	 * @param entily
	 * @return
	 */
	public T clearDefaultValue(T entily) {

		Field[] fieldArr = entily.getClass().getDeclaredFields();
		Field[] superFields = entily.getClass().getSuperclass().getDeclaredFields();
		List<Field> fields = Lists.newArrayList(fieldArr);
		fields.addAll(Lists.newArrayList(superFields));
		// 循环获取字段名称数据
		for (int i = 0; i < fields.size(); i++) {
			// 获取当前的属性名称
			String name = fields.get(i).getName();
			// 判断当前是否为序列号名称 （序列号名称必须为：serialVersionUID ，否则会报NoSuchMethodException异常）
			if ("serialVersionUID".equals(name)) {
				//跳出当前循环，进入下一次循环
				continue;
			}

			//将属性的首先字符大写，方便构造GET，SET方法
			name = name.substring(0, 1).toUpperCase() + name.substring(1);
			try {
				// 获取属性类型
				String typeName = fields.get(i).getGenericType().toString();
				// 获取属性GET方法
				Method get = entily.getClass().getMethod("get" + name);
				// 通过属性的GET方法获取属性对应值
				Object value = get.invoke(entily);
				// 判断属性类型为BigDecimal类型

                /*

                if ("class java.math.BigDecimal".equals(typeName)) {
                    // 属性对应值是否为空
                    if (value != null) {
                        if (OrderConstant.DEFAULT_BIGDECIMAL_VALUE.compareTo((BigDecimal) value) == 0) {
                            // 获取属性SET方法（注意：方法的参数值类型必须设置正确，则报方法不存在异常）
                            Method set = entily.getClass().getMethod("set" + name, BigDecimal.class);
                            // 通过SET方法给予赋值
                            set.invoke(entily, (BigDecimal) null);
                        }
                    }
                }
                // 判断属性类型为Long类型
                if ("class java.lang.Long".equals(typeName)) {
                    if (value != null) {
                        if (OrderConstant.DEFAULT_LONG_VALUE.compareTo((Long) value) == 0) {
                            Method set = entily.getClass().getMethod("set" + name, Long.class);
                            set.invoke(entily, (Long) null);
                        }
                    }
                }
                // 判断属性类型为Long类型
                if ("class java.lang.Integer".equals(typeName)) {
                    if (value != null) {
                        if (OrderConstant.DEFAULT_INTEGER_VALUE.compareTo((Integer) value) == 0) {
                            Method set = entily.getClass().getMethod("set" + name, Integer.class);
                            if ("valid".equals(name)) {
                            } else {
                                set.invoke(entily, (Integer) null);
                            }
                        }
                    }
                }
                // 判断属性类型为Double类型
                if ("class java.lang.Double".equals(typeName)) {
                    if (value != null) {
                        if (OrderConstant.DEFAULT_DOUBLE_VALUE.compareTo((Double) value) == 0) {
                            Method set = entily.getClass().getMethod("set" + name, String.class);
                            set.invoke(entily, (Double) null);
                        }
                    }
                }
                // 判断属性类型为Long类型
                if ("class java.lang.Float".equals(typeName)) {
                    if (value != null) {
                        if (OrderConstant.DEFAULT_FLOAT_VALUE.equals(value)) {
                            Method set = entily.getClass().getMethod("set" + name, String.class);
                            set.invoke(entily, (String) null);
                        }
                    }
                }
                // 判断属性类型为String类型
                if ("class java.lang.String".equals(typeName)) {
                    if (value != null) {
                        if (OrderConstant.DEFAULT_STRING_VALUE.equals(value)) {
                            Method set = entily.getClass().getMethod("set" + name, String.class);
                            set.invoke(entily, (String) null);
                        }
                    }
                }

                 */
				// 判断属性类型为Date类型
				if ("class java.utils.Date".equals(typeName)) {
					if (value != null) {
						if (BaseConstant.DEFAULT_DATE.compareTo((Date) value) == 0) {
							Method set = entily.getClass().getMethod("set" + name, Date.class);
							set.invoke(entily, (Date) null);
						}
					}
				}
                /*
                // 判断属性类型为Date类型
                if ("class java.time.Instant".equals(typeName)) {
                    if (value != null) {
                        if (OrderConstant.DEFAULT_INSTANT_VALUE.compareTo((Instant) value) == 0) {
                            Method set = entily.getClass().getMethod("set" + name, Instant.class);
                            set.invoke(entily, (Instant) null);
                        }
                    }
                }

                // 判断属性类型为LocalDate类型
                if ("class java.time.LocalDate".equals(typeName)) {
                    if (value != null) {
                        if (OrderConstant.DEFAULT_LOCALDATE_VALUE.compareTo((LocalDate) value) == 0) {
                            Method set = entily.getClass().getMethod("set" + name, LocalDate.class);
                            set.invoke(entily, (LocalDate) null);
                        }
                    }
                }
                // 判断属性类型为LocalDateTime类型
                if ("class java.time.LocalDateTime".equals(typeName)) {
                    if (value != null) {
                        if (OrderConstant.DEFAULT_LOCALDATETIME_VALUE.compareTo((LocalDateTime) value) == 0) {
                            Method set = entily.getClass().getMethod("set" + name, LocalDateTime.class);
                            set.invoke(entily, (LocalDateTime) null);
                        }
                    }
                }
                */

			} catch (Exception e) {
				log.error(e.getMessage(), e);
			}
		}
		log.info("结束的参数,{}", entily);
		return entily;
	}
}
